package com.tianquan.miracle.beans;

import com.tianquan.miracle.aop.AopEntity;
import com.tianquan.miracle.conditional.ParseConditionPostProcessor;
import com.tianquan.miracle.postprocessor.BeanPostProcessor;
import com.tianquan.miracle.postprocessor.InjectBeanPostProcessor;
import com.tianquan.miracle.proxy.PoxyFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: tianquan
 * @date: 2024-10-11  12:26
 * @Description: 抽象的通用Bean处理器类，提供了Bean后置处理和AOP代理处理的功能
 */
public abstract class AbstractCommonBeanProcessor {

    /**
     * 依赖注入处理器列表，用于存储所有注册的依赖注入后置处理器
     */
    final List<InjectBeanPostProcessor> injectBeanPostProcessors = new ArrayList<>(16);

    /**
     * 解析Condition系列注解的处理器列表，用于存储所有注册的解析Condition注解的后置处理器
     */
    final List<ParseConditionPostProcessor> parseConditionPostProcessors = new ArrayList<>(16);

    /**
     * 需要走代理的注解映射，键为注解类，值为对应的AopEntity对象
     */
    final Map<Class<? extends Annotation>, AopEntity> aopAnnotationMap = new HashMap<>();

    /**
     * 需要走代理的方法映射，键为方法名，值为对应的AopEntity对象
     */
    final Map<String, AopEntity> aopMethodsNameMap = new HashMap<>();

    /**
     * 需要走代理的类映射，键为类，值为对应的AopEntity对象
     */
    final Map<Class<?>, AopEntity> aopClassMap = new HashMap<>();

    /**
     * Bean后置处理器列表，用于存储所有注册的Bean后置处理器
     */
    final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>(16);

    /**
     * 向aopAnnotationMap中添加需要走代理的注解
     *
     * @param annotation 需要代理的注解类
     * @param aopEntity  包含代理信息的实体对象
     */
    public void putAopAnnotationName(Class<? extends Annotation> annotation, AopEntity aopEntity) {
        aopAnnotationMap.put(annotation, aopEntity);
    }

    /**
     * 向aopMethodsNameMap中添加需要走代理的方法名
     *
     * @param method    需要代理的方法名
     * @param aopEntity 包含代理信息的实体对象
     */
    public void putAopMethodsName(String method, AopEntity aopEntity) {
        aopMethodsNameMap.put(method, aopEntity);
    }

    /**
     * 向aopClassMap中添加需要走代理的类
     *
     * @param className 需要代理的类
     * @param aopEntity 包含代理信息的实体对象
     */
    public void putAopClass(Class<?> className, AopEntity aopEntity) {
        aopClassMap.put(className, aopEntity);
    }

    /**
     * 添加依赖注入后置处理器到injectBeanPostProcessors列表中
     *
     * @param beanPostProcessors 依赖注入后置处理器列表
     */
    public void addInjectBeanPostProcessors(List<InjectBeanPostProcessor> beanPostProcessors) {
        this.injectBeanPostProcessors.addAll(beanPostProcessors);
    }

    /**
     * 添加解析Condition注解的后置处理器到parseConditionPostProcessors列表中
     *
     * @param beanPostProcessors 解析Condition注解的后置处理器列表
     */
    public void addParseConditionPostProcessors(List<ParseConditionPostProcessor> beanPostProcessors) {
        this.parseConditionPostProcessors.addAll(beanPostProcessors);
    }

    /**
     * 判断是否有必要的创建对象的代理类
     *
     * @param bean 需要判断是否创建代理类的Bean对象
     * @return 如果需要创建代理类，则返回代理对象；否则返回原对象
     */
    protected Object isNecessaryCreateProxy(Object bean) {
        Class<?> aClass = bean.getClass();
        // 当前bean的所有方法
        List<String> currentBeanAllMethods = Arrays.stream(bean.getClass().getDeclaredMethods())
                .map(Method::getName)
                .collect(Collectors.toList());

        // 整个类的方法是否都要增强
        AopEntity aopEntity = aopClassMap.get(aClass);
        if (aopEntity != null) {
            return PoxyFactory.getProxy(bean, currentBeanAllMethods,
                    aopEntity.getBeforeMethod(), aopEntity.getAroundMethod(), aopEntity.getAfterMethod(), aopEntity.getObject()
            );
        }

        // 某些方法需要生成代理
        List<String> proxyMethods = aopMethodsNameMap.keySet().stream()
                .filter(methodName -> currentBeanAllMethods.stream().anyMatch(poxyMethodName -> poxyMethodName.equals(methodName)))
                .collect(Collectors.toList());

        if (!proxyMethods.isEmpty()) {
            aopEntity = aopMethodsNameMap.get(proxyMethods.get(0));
        }

        // 注解
        for (Method method : aClass.getDeclaredMethods()) {
            for (Annotation annotation : method.getAnnotations()) {
                aopEntity = aopAnnotationMap.get(annotation.annotationType());
                if (aopEntity == null) {
                    continue;
                }
                proxyMethods.add(method.getName());
                break;
            }
        }

        if (!proxyMethods.isEmpty()) {
            return PoxyFactory.getProxy(bean, proxyMethods,
                    aopEntity.getBeforeMethod(), aopEntity.getAroundMethod(), aopEntity.getAfterMethod(), aopEntity.getObject()
            );
        }

        // 不需要走代理
        return bean;
    }

    /**
     * 获取所有注册的Bean后置处理器列表
     *
     * @return Bean后置处理器列表
     */
    public List<BeanPostProcessor> getBeanPostProcessors() {
        return beanPostProcessors;
    }

    /**
     * 向beanPostProcessors列表中添加Bean后置处理器
     *
     * @param beanPostProcessor 要添加的Bean后置处理器
     */
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        beanPostProcessors.add(beanPostProcessor);
    }

    /**
     * 抽象方法，用于选择特定类型的Bean
     *
     * @param beanClass Bean的类型
     * @return 特定类型的Bean列表
     */
    public abstract <T> List<T> selectBean(Class<T> beanClass);
}

